home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / GLUT-3.7 / PROGS / DEMOS / SKYFLY / DATABASE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-12  |  15.8 KB  |  523 lines

  1.  
  2. /*
  3.  * database.c   $Revision: 1.2 $
  4.  */
  5.  
  6. #include <stdlib.h>
  7. #include <stdio.h>
  8. #include <math.h>
  9. #include "skyfly.h"
  10.  
  11. #if defined(_WIN32)
  12. #pragma warning (disable:4244)  /* disable bogus conversion warnings */
  13. #pragma warning (disable:4305)  /* VC++ 5.0 version of above warning. */
  14. #endif
  15.  
  16. #define cosf(a)        cos((float)a)
  17. #define sinf(a)      sin((float)a)
  18. #define sqrtf(a)      sqrt((float)a)
  19. #define expf(a)      exp((float)a)
  20.  
  21. static void create_terrain(void);
  22. static void erode_terrain(void);
  23. static void color_terrain(void);
  24. static void init_cells(void);
  25. static void put_cell(float *source, perfobj_t *pobj);
  26. static void put_paper_plane(float *source, perfobj_t *pobj);
  27. static void put_texture_bind(int bind, perfobj_t *pobj);
  28.  
  29. int clouds;
  30. static float paper_plane_vertexes[] = {
  31. /*Nx  Ny  Nz   Vx     Vy    Vz */
  32. /* ----------------------------    Top view of plane, middle streached open  */
  33.  0.2, 0., .98, -.10,    0,  .02,/* vertex #'s      4 (.48,0,-.06)            */
  34.  0., 0., 1.,   -.36,  .20, -.04,/*                 .                         */
  35.  0., 0., 1.,    .36,  .01,    0,/*                ...                        */
  36.  0., 0.,-1.,   -.32,  .02,    0,/*                 .             +X          */
  37.  0., 1., 0.,    .48,    0, -.06,/*               2 . 6,8          ^          */
  38.  0., 1., 0.,   -.30,    0, -.12,/*               . . .            |          */
  39.  0.,-1., 0.,    .36, -.01,    0,/*              .. . ..           |          */
  40.  0.,-1., 0.,   -.32, -.02,    0,/*               . . .            |          */
  41.  0., 0.,-1.,    .36, -.01,    0,/*             . . . . .  +Y<-----*          */
  42.  0., 0.,-1.,   -.36, -.20, -.04,/*               . . .     for this picture  */
  43.  -0.2, 0., .98,  -.10,  0,  .02,/*            .  . . .  .  coord system rot. */
  44.  -0.2, 0., -.98, -.10,  0,  .02,/*               . . .     90 degrees        */
  45.  0., 0., -1.,  -.36,  .20, -.04,/*           .   . . .   .                   */
  46.  0., 0., -1.,   .36,  .01,    0,/*               . # .           # marks     */
  47.  0., 0., 1.,   -.32,  .02,    0,/*          .    . . .    .   (0,0) origin   */
  48.  0., -1., 0.,   .48,    0, -.06,/*               . . .         (z=0 at top   */
  49.  0., -1., 0.,  -.30,    0, -.12,/*         .     0 . 10    .    of plane)    */
  50.  0.,1., 0.,     .36, -.01,    0,/*             . . . . .                     */
  51.  0.,1., 0.,    -.32, -.02,    0,/*        .  .   . . .   .  .                */
  52.  0., 0.,1.,     .36, -.01,    0,/*         .     . . .     .                 */
  53.  0., 0.,1.,    -.36, -.20, -.04,/*       1.......3.5.7.......9               */
  54.  0.2, 0., -.98,  -.10,  0,  .02,/* (-.36,.2,-.04)                            */
  55. };
  56.  
  57. #define SIZE    400
  58.  
  59. float *A;
  60.  
  61. void init_paper_planes(void)
  62. {
  63.     perfobj_t       *pobj;
  64.  
  65.     /* 
  66.      * create various perf-objs for planes 
  67.      */
  68.     pobj = &(SharedData->paper_plane_obj);
  69.     pobj->flags = SharedData->paper_plane_flags;
  70.     pobj->vdata = (float *) SharedData->paper_plane_verts;
  71.     put_paper_plane(paper_plane_vertexes, pobj);
  72.  
  73.     pobj = &(SharedData->paper_plane_start_obj);
  74.     pobj->flags = SharedData->paper_plane_start_flags;
  75.     *(pobj->flags) = PD_PAPER_PLANE_MODE;
  76.     *(pobj->flags + 1) = PLANES_START;
  77.     *(pobj->flags + 2) = PD_END;
  78.  
  79.     pobj = &(SharedData->paper_plane_2ndpass_obj);
  80.     pobj->flags = SharedData->paper_plane_2ndpass_flags;
  81.     *(pobj->flags) = PD_PAPER_PLANE_MODE;
  82.     *(pobj->flags + 1) = PLANES_SECOND_PASS;
  83.     *(pobj->flags + 2) = PD_END;
  84.  
  85.     pobj = &(SharedData->paper_plane_end_obj);
  86.     pobj->flags = SharedData->paper_plane_end_flags;
  87.     *(pobj->flags) = PD_PAPER_PLANE_MODE;
  88.     *(pobj->flags + 1) = PLANES_END;
  89.     *(pobj->flags + 2) = PD_END;
  90. }
  91.  
  92.  
  93. /*
  94.  * create perfobj from static definition of plane geometry above
  95.  */
  96.  
  97. static void put_paper_plane(float *source, perfobj_t *pobj)
  98. {
  99.     int             j;
  100.     perfobj_vert_t *pdataptr =(perfobj_vert_t *) pobj->vdata;
  101.     unsigned int  *flagsptr = pobj->flags;
  102.     float          *sp = source;
  103.  
  104.     *flagsptr++ = PD_DRAW_PAPER_PLANE;
  105.  
  106.     for (j = 0; j < 22; j++) {
  107.         putn3fdata(sp + 0, pdataptr);
  108.         putv3fdata(sp + 3, pdataptr);
  109.  
  110.         sp += 6;
  111.         pdataptr++;
  112.     }
  113.     *flagsptr++ = PD_END;
  114.  
  115. }
  116.  
  117. static void put_texture_bind(int bind, perfobj_t *pobj)
  118. {
  119.     unsigned int  *flagsptr = pobj->flags;
  120.  
  121.     *flagsptr++ = PD_TEXTURE_BIND;
  122.     *flagsptr++ = bind;
  123.  
  124.     *flagsptr++ = PD_END;
  125.  
  126. }
  127.  
  128. static void put_clouds_vert(float s, float t, float x, float y, float z,
  129.                 perfobj_vert_t *pdataptr)
  130. {
  131.     float           D[5];
  132.     D[0] = s;
  133.     D[1] = t;
  134.     D[2] = x;
  135.     D[3] = y;
  136.     D[4] = z;
  137.     putt2fdata(D, pdataptr);
  138.     putv3fdata(D + 2, pdataptr);
  139. }
  140.  
  141. float S[SIZE][SIZE];
  142. float T[SIZE][SIZE];
  143. float C[SIZE][SIZE][3];
  144. int   M[SIZE][SIZE];
  145.  
  146. void init_terrain(void)
  147. {
  148.     GridDim = CellDim * NumCells;
  149.     XYScale = (float)GRID_RANGE / (float)GridDim;
  150.     CellSize = (float)GRID_RANGE / (float)NumCells;
  151.  
  152.     create_terrain();
  153.     erode_terrain();
  154.     color_terrain();
  155.     init_cells();
  156. }
  157.  
  158. #define SKY                             50.
  159.  
  160. void init_clouds(void)
  161. {
  162.     perfobj_t *pobj;
  163.     perfobj_vert_t *pdataptr;
  164.  
  165.     clouds = 0;
  166.     pobj = &(SharedData->clouds_texture_obj);
  167.     pobj->flags = SharedData->clouds_texture_flags;
  168.     put_texture_bind(2,pobj);
  169.  
  170.     pobj = &(SharedData->clouds_obj);
  171.     pobj->flags = SharedData->clouds_flags;
  172.     pobj->vdata = (float *)SharedData->clouds_verts;
  173.     *(pobj->flags+ 0) = PD_DRAW_CLOUDS;
  174.     *(pobj->flags+ 1) = PD_END;
  175.  
  176.     pdataptr =(perfobj_vert_t *) pobj->vdata;
  177.  
  178.     put_clouds_vert(0.,0., -SKY, -SKY, SKY_HIGH,pdataptr);
  179.     pdataptr++;
  180.     put_clouds_vert(24.,0.,  SKY+GRID_RANGE, -SKY, SKY_HIGH,pdataptr);
  181.     pdataptr++;
  182.     put_clouds_vert(24.,24.,  SKY+GRID_RANGE,  SKY+GRID_RANGE, SKY_HIGH,pdataptr);
  183.     pdataptr++;
  184.     put_clouds_vert(0.,24., -SKY,  SKY+GRID_RANGE, SKY_HIGH,pdataptr);
  185. }
  186.  
  187. static void create_terrain(void)
  188. {
  189.     int             r, c, i, x1, y1, x2, y2;
  190.     int             hillsize;
  191.  
  192.     hillsize = GRID_RANGE / 12;
  193.  
  194.     A = (float*)calloc(GridDim * GridDim, sizeof(float));
  195.  
  196.     /*
  197.      *  initialize elevation to zero, except band down middle
  198.      *  where make a maximum height 'hill' that will later be
  199.      *  inverted to make the negative elevation 'canyon'
  200.      */
  201.  
  202.     for (r = 0; r < GridDim; r++)
  203.         for (c = 0; c < GridDim; c++)
  204.              if(r>=(GridDim/2-2-IRND(2)) && r<=(GridDim/2+2+IRND(2)))
  205.                 A[r * GridDim + c] = 1.0;
  206.              else
  207.                 A[r * GridDim + c] = 0.0;
  208.  
  209.     /*
  210.      * create random sinusoidal hills that add on top
  211.      * of each other
  212.      */
  213.     for (i = 1; i <= 10*GridDim; i++) {
  214.  
  215.         /* randomly position hill */
  216.         x1 = IRND(GridDim - hillsize);
  217.         x2 = x1 + hillsize/ 8 + IRND(hillsize-hillsize/ 8);
  218.         y1 = IRND(GridDim - hillsize);
  219.         y2 = y1 + hillsize/ 8 + IRND(hillsize-hillsize/ 8);
  220.  
  221.         if((x1<=GridDim/2-4 && x2>=GridDim/2-4) || 
  222.            (x1<=GridDim/2+4 && x2>=GridDim/2+4))
  223.         {
  224.             x1 = IRND(2)-2 + GridDim/2;
  225.             x2 = x1 + IRND(GridDim/2 - x1 + 2);
  226.         }
  227.  
  228.         /* make a sinusoidal hill */
  229.         for (r = x1; r < x2; r++)
  230.             for (c = y1; c < y2; c++) {
  231.                 A[r * GridDim + c] +=.35 *
  232.                     (sinf(M_PI * (float) (r - x1) / (float) (x2 - x1)) *
  233.                      (sinf(M_PI * (float) (c - y1) / (float) (y2 - y1))));
  234.             }
  235.     }
  236.  
  237.     /* clamp the elevation of the terrain */
  238.     for (r = 1; r < GridDim; r++)
  239.         for (c = 1; c < GridDim; c++) {
  240.             A[r * GridDim + c] = MIN(A[r * GridDim + c], .95);
  241.             A[r * GridDim + c] = MAX(A[r * GridDim + c], 0.);
  242.         }
  243.  
  244. }
  245.  
  246. #define NUM_DROPS                       80
  247.  
  248. static void erode_terrain(void)
  249. {
  250.     float           x, y, xv, yv, dx, dy;
  251.     float           cut, min, take;
  252.     int             nm;
  253.     int             t, xi, yi, xo, yo, done;
  254.     int             ii, jj, r, c;
  255.  
  256.     for (nm = 1; nm < NUM_DROPS*GridDim; nm++) {
  257.  
  258.         /* find a random position to start the 'rain drop' */
  259.         x = (float) (IRND(GridDim));
  260.         y = (float) (IRND(GridDim));
  261.  
  262.         /* Clamp x and y to be inside grid */
  263.         x = MIN(MAX(2., x), (float)GridDim-2.);
  264.         y = MIN(MAX(2., y), (float)GridDim-2.);
  265.         
  266.         done = 0;
  267.         yv = xv = 0.;
  268.  
  269.         t = 0;
  270.         cut = .3;
  271.  
  272.         while (!done) {
  273.             xi = (int) x;
  274.             yi = (int) y;
  275.  
  276.             min = 90.;
  277.  
  278.             if (xi != xo || yi != yo) {
  279.                 cut *=.99;
  280.  
  281.                 /* gradient */
  282.                 dx = (A[(xi + 1)*GridDim + yi] - A[(xi - 1) * GridDim + yi]);
  283.                 dy = (A[xi * GridDim + yi + 1] - A[xi * GridDim + yi - 1]);
  284.  
  285.  
  286.                 /* find lowest neighbor */
  287.                 for (ii = -1; ii <= 1; ii++)
  288.                     for (jj = -1; jj <= 1; jj++)
  289.                         if (A[(xi + ii)*GridDim + yi + jj] < min)
  290.                             min = A[(xi + ii)*GridDim + yi + jj];
  291.  
  292.                 /* evaporate drop if sitting on my old location */
  293.                 if (M[xi][yi] == nm)
  294.                     done = 1;
  295.                 M[xi][yi] = nm;
  296.  
  297.                 /* cave in neighbors by .3  */
  298.                 for (ii = -1; ii <= 1; ii++)
  299.                     for (jj = -1; jj <= 1; jj++) {
  300.                         take =.3 * cut * (A[(xi + ii)*GridDim + yi + jj]-min);
  301.                         A[(xi + ii)*GridDim + yi + jj] -= take;
  302.                     }
  303.  
  304.                 /* take away from this cell by .7 */
  305.                 take = (A[xi*GridDim + yi] - min) *.7 * cut;
  306.                 A[xi*GridDim + yi] -= take;
  307.  
  308.             }
  309.             xo = xi;
  310.             yo = yi;
  311.  
  312.             /* move drop using kinematic motion*/
  313.             xv = xv - dx -.8 * xv;
  314.             yv = yv - dy -.8 * yv;
  315.  
  316.             x += xv;
  317.             y += yv;
  318.  
  319.             /*
  320.              * make sure can't move by more that 1.0
  321.              * in any direction 
  322.              */
  323.  
  324.             xv = MAX(xv, -1);
  325.             yv = MAX(yv, -1);
  326.             xv = MIN(xv,  1);
  327.             yv = MIN(yv,  1);
  328.  
  329.             /* check to see if need a new drop */
  330.             /* ie ran of world, got stuck, or at 'sea level' */
  331.             if (x < 1.|| x > GridDim - 1.|| y < 1.|| y > GridDim - 1.
  332.                                                 || t++ > 2000
  333.                 || cut <.01)
  334.                 done = 1;
  335.  
  336.             if (A[xi*GridDim + yi] < 0.0001) {
  337.                 A[xi*GridDim + yi] = 0.;
  338.                 done = 1;
  339.             }
  340.         }                       /* while (!done) with this drop */
  341.     }                           /* next drop */
  342.  
  343.     /*
  344.      *  invert the pseudo hill int the pseudo canyon
  345.      */
  346.  
  347.     for (r = 0; r < GridDim; r++)
  348.         for (c = 0; c < GridDim; c++)
  349.              if(r>=GridDim/2-4 && r<=GridDim/2+4)
  350.                 A[r * GridDim + c] = MAX((-3.2 * A[r * GridDim + c]), -1.8);
  351. }
  352.  
  353. static void color_terrain(void)
  354. {
  355.     float           N[3], D, alt, maxelev = -1.;
  356.     int             x, y;
  357.  
  358.     for (x = 0; x < GridDim; x++)
  359.         for (y = 0; y < GridDim; y++)
  360.             maxelev = MAX(maxelev, A[x * GridDim + y]);
  361.  
  362.     for (x = 1; x < GridDim - 1; x++)
  363.         for (y = 1; y < GridDim - 1; y++) {
  364.             alt = A[x * GridDim + y] * 1.5;
  365.             /* randomly perterb to get a mottling effect */
  366.             alt += IRND(100) / 400. -.125;
  367.             alt = MIN(alt, 1.0);
  368.             if (alt < -.11) {
  369.                 C[x][y][0] = 0.6;         /* soil/rock in canyon */
  370.                 C[x][y][1] = 0.5;
  371.                 C[x][y][2] = 0.2;
  372.             } else if (alt < .000001) {
  373.                 C[x][y][0] = 0.0;         /* dark, jungle lowlands */
  374.                 C[x][y][1] = 0.2;
  375.                 C[x][y][2] = 0.05;
  376.             } else if (alt <.90) {
  377.                 C[x][y][0] = alt*.25;     /* green to redish hillsides */
  378.                 C[x][y][1] = (1.0 - alt) *.4 + .1;
  379.                 C[x][y][2] = 0.1;
  380.             } else {
  381.                 C[x][y][0] = alt;
  382.                 C[x][y][1] = alt;         /* incresingly white snow */
  383.                 C[x][y][2] = alt;
  384.             }
  385.  
  386.             /* compute normal to terrain */
  387.  
  388.             N[0] = A[(x - 1)*GridDim + y] - A[(x + 1)*GridDim + y];
  389.             N[1] = A[x*GridDim + y - 1] - A[x*GridDim + y + 1];
  390.             N[2] = 2.0 / ScaleZ;
  391.  
  392.             D = 1.0 / sqrtf(N[0] * N[0] + N[1] * N[1] + N[2] * N[2]);
  393.  
  394.             N[0] *= D;
  395.             N[1] *= D;
  396.             N[2] *= D;
  397.  
  398.             /* perform diffuse lighting of terrain */
  399.  
  400.             D = N[0] * LX + N[1] * LY + N[2] * LZ;
  401.             D *= 1.2;
  402.  
  403.             if(!IRND(4)) D *= .5;
  404.         
  405.             D = MAX(D,0);
  406.  
  407.             /* darken terrain on shaded side */
  408.             C[x][y][0] *= D;
  409.             C[x][y][1] *= D;
  410.             C[x][y][2] *= D;
  411.  
  412.             S[x][y] = (float) (x) / (float)CellDim;
  413.             T[x][y] = (float) (y) / (float)CellDim;
  414.  
  415.         }
  416. }
  417.  
  418. /*
  419.  * create perobj to hold a cell of terrain
  420.  * for a 5x5 terrain cell, there will be 5
  421.  * tmeshes each with 10 triangles (12 vertexes)
  422.  * this means looking past my cell to neighbors
  423.  * to stitch things together.  To keep data contigious,
  424.  * vertexes are repeated in tmeshes, not shared.
  425.  */
  426.  
  427. static void init_cells(void)
  428. {
  429.     int             x, y, xx, yy, world_x, world_y;
  430.     int             pntr, index, sstart, tstart;
  431.     float           *D;
  432.     perfobj_t       *pobj;
  433.  
  434.     D = (float*)calloc(CellDim *(CellDim + 1) * 
  435.                         2 * FLOATS_PER_VERT_PAIR, sizeof(float));
  436.  
  437.     pobj = &(SharedData->terrain_texture_obj);
  438.     pobj->flags = SharedData->terrain_texture_flags;
  439.  
  440.     put_texture_bind(1, pobj);
  441.  
  442.     for (x = 0; x < NumCells; x++)
  443.         for (y = 0; y < NumCells; y++) {
  444.             index = x*NumCells+y;
  445.             SharedData->terrain_cells[index].flags = 
  446.                 SharedData->terrain_cell_flags[index];
  447.  
  448.             SharedData->terrain_cells[index].vdata =
  449.                 (float *) SharedData->terrain_cell_verts[index];
  450.  
  451.             pntr = 0;
  452.  
  453.             /*
  454.              * Guarantee S,T to be within range 0-8 for tmesh strip using
  455.              * 256x256 sized texture. This avoids texture index clipping
  456.              * in pipe. 
  457.             */
  458.             sstart = (int)S[x*CellDim][y*CellDim];
  459.             tstart = (int)T[x*CellDim][y*CellDim];
  460.  
  461.             for (xx = 0; xx < CellDim; xx++)
  462.                 for (yy = 0; yy < CellDim + 1; yy++) {
  463.  
  464.                     /* init a perfobj */
  465.  
  466.                     world_x = MIN(x * CellDim + xx, GridDim-2);
  467.                     world_y = MIN(y * CellDim + yy, GridDim-2);
  468.  
  469.                     D[pntr + 0] = S[world_x][world_y] - sstart;
  470.                     D[pntr + 1] = T[world_x][world_y] - tstart;
  471.                     D[pntr + 2] = C[world_x][world_y][0];
  472.                     D[pntr + 3] = C[world_x][world_y][1];
  473.                     D[pntr + 4] = C[world_x][world_y][2];
  474.                     D[pntr + 5] = (float)world_x * XYScale;
  475.                     D[pntr + 6] = (float)world_y * XYScale;
  476.                     D[pntr + 7] = A[world_x*GridDim + world_y]*ScaleZ;
  477.  
  478.  
  479.                     D[pntr + 8] = S[world_x + 1][world_y] - sstart;
  480.                     D[pntr + 9] = T[world_x + 1][world_y] - tstart;
  481.                     D[pntr + 10] = C[world_x + 1][world_y][0];
  482.                     D[pntr + 11] = C[world_x + 1][world_y][1];
  483.                     D[pntr + 12] = C[world_x + 1][world_y][2];
  484.                     D[pntr + 13] = (float)(world_x+1) * XYScale;
  485.                     D[pntr + 14] = (float)world_y * XYScale;
  486.                     D[pntr + 15] = A[(world_x+1)*GridDim + world_y] * ScaleZ;
  487.  
  488.                     pntr += FLOATS_PER_VERT_PAIR;
  489.  
  490.                 }               /* for each cell */
  491.             put_cell(D, &(SharedData->terrain_cells[index]));
  492.  
  493.         }                       /* for all cells in world */
  494.  
  495.         free(D);
  496. }
  497.  
  498. static void put_cell(float *source, perfobj_t *pobj)
  499. {
  500.     int             i, j;
  501.     perfobj_vert_t *pdataptr =(perfobj_vert_t *) pobj->vdata;
  502.     unsigned int  *flagsptr = pobj->flags;
  503.     float          *sp = source;
  504.  
  505.     /* For all tmesh strips in cell */
  506.     for (i = 0; i < CellDim; i++) {
  507.         *flagsptr++ = PD_DRAW_TERRAIN_CELL;
  508.         *flagsptr++ = (unsigned long) pdataptr;
  509.  
  510.         /* For all verts in tmesh strip */
  511.         for (j = 0; j < (CellDim + 1) * 2; j++) {
  512.             putt2fdata(sp, pdataptr);
  513.             putc3fdata(sp + 2, pdataptr);
  514.             putv3fdata(sp + 5, pdataptr);
  515.  
  516.             sp += 8;
  517.             pdataptr++;
  518.         }
  519.     }
  520.     *flagsptr++ = PD_END;
  521. }
  522.  
  523.